
#ifndef APP_GLOBALS_NETWORK
#define APP_GLOBALS_NETWORK
#include <includes.h>
#include "app_network.h"
#include "WIFI.h"
#include "WIFI_Driver.h"
#include "app_Memory.h"

// 函数声明
void NetWork_ClrTestFisishFlag(void);

// 局部宏定义
#define TEMPBUFF_DATA_SIZE                          1200        // 临时缓冲大小

//外部引用变量
extern uint8_t TemArrRxBuffer[2][DMARxBuffer];                  // 存储接收
extern uint8_t ucStatus;                                        // 状态机的当前状态序号，也就是状态机结构体数组的下标
extern uint16_t sRecv_LEN;                                      // DMA的串口缓存中接收到的数据长度
extern struct HeartBeatReport heartBeatReport_st;               // 心跳包结构体
extern const SGPRS_AT *pGPRS_AT;                                // 当前状态机
extern uint8_t already_send_transient;                          // 已经发送瞬态包

//局部变量
static uint8_t curveDataSending = 0;                            // 正在发送曲线数据
static uint8_t HandleFlag = 0;                                  // 完成处理标志 0-已完成 1-处理中
static NetWorkTestData_ST netWorkTestData_st = {0};             // 测试数据结构体
static uint8_t testDataRecvResult = 0;                          // 测试数据服务器响应结果   1失败  2成功
static uint8_t network_TmepDataBuff[TEMPBUFF_DATA_SIZE] = {0};  // 临时数据缓冲区
static uint8_t network_ParseBuffer[DMARxBuffer] = {0};          // tcp拆包黏包处理缓冲
static NetWorkTestProc_ST networkTestProc_st = {0};             // 工作测试流程标志
static const uint8_t NetworkString_TUANCHENG[] = "TUANCHENG";   // 数据发送标头
static const uint8_t realTimeEnableTable[20] = NetWork_RtDataEnableTable;

//全局变量
uint8_t UpEepromOK;                                              // 更新EEPROM完成
uint16_t WifiReportSyncID;                                       // 同步ID Report 0x8000->0xffff; Check 0x0000->0x7fff
uint8_t workProcess = 0;                                         // 测试数据发送流程状态

/******************************** 命令数据组织函数 *************************/

/// @brief 获取模块序列号
/// @param Buffer 接收缓冲
void NetWork_GetModuleIDString(uint8_t *Buffer){
    *(Buffer++) = 'A';
    *(Buffer++) = 'V';
    *(Buffer++) = 'R';
    *(Buffer++) = 'T';
    *(Buffer++) = 'E';
    *(Buffer++) = 'S';
    *(Buffer++) = 'T';
    *(Buffer++) = '-';
    Comm_IntegerToString(Buffer, share_parameterCfgData_st.baseData_st.SerialNumber, 10);
    Buffer += 10;
    *(Buffer++) = '\0';
    *(Buffer++) = '\0';
}

/// @brief 更新WIFI同步ID
/// @param  none
/// @return 同步ID号
uint16_t NetWork_UpdateWifiSyncID(void){
    uint8_t os_err = 0;
    uint16_t TempSyncID;

    // 获取信号量
    OSSemPend(App_Sem_NETWORKTX, 0, &os_err);
    WifiReportSyncID++;
    if (WifiReportSyncID < 0x8000)
        WifiReportSyncID = 0x8000;
    TempSyncID = WifiReportSyncID;
    //释放信号量
    if (OSSemPost(App_Sem_NETWORKTX) != OS_ERR_NONE)
        SYS_DebugERROR;
    return (TempSyncID);
}

/// @brief 时区时间计算
/// @param pTimeBuff 时间数据
/// @param zone 时区
/// @return 本地时间戳
static uint32_t NetWork_ConvertTimeFromZone(uint32_t timestamp, uint16_t zone){
    int8_t i;
    uint32_t ulTime = timestamp;

    if (zone & 0x8000){ // 时区
        zone = ~zone + 1;
        for (i = 0; i < zone; i++)
            ulTime -= 3600;
    }
    else{
        for (i = 0; i < zone; i++)
            ulTime += 3600;
    }
    return ulTime;
}

/// @brief 数据组织统一接口
/// @param data 数据内容
/// @param dataLen 数据内容长度（不包含基础协议长度）
/// @param extendData 扩展字段内容
/// @param cmd 操作命令
/// @param syncID 同步ID
/// @param sendLen 数据发送长度（有其他函数检测该值，不为零会启动DMA进行发送）
/// @return 0失败  1成功
uint8_t NetWork_DataFeedback(uint8_t * data, uint16_t dataLen, uint8_t * extendData, uint8_t cmd, uint16_t syncID,uint32_t * sendLen){
    uint8_t  * Point = data;
    uint16_t totalNumber = dataLen + DataFrameLength_Min;
    uint16_t Checksum = 0;

    // 标头
    strncpy((char *)Point, (char *)NetworkString_TUANCHENG, 9);
    Point += 9;
    // 数据长度
    *(Point++) = (uint8_t)(totalNumber>> 8);
    *(Point++) = (uint8_t)(totalNumber);
    // 序列号
    NetWork_GetModuleIDString(Point);
    Point += 20;
    // 操作命令
    *(Point++) = cmd;
    // 同步ID
    *(Point++) = (uint8_t)(syncID >> 8);
    *(Point++) = (uint8_t)(syncID);
    // 保留字段(12字节)
    memcpy(Point, extendData, DataFrameLength_Extend);
    Point += DataFrameLength_Extend;
    // 数据内容
    /* 调用该函数的父函数需要组织好数据 */
    Point += dataLen;
    // 计算校验和
    Checksum = Comm_CalCheckSum(data, totalNumber - 2);
    *(Point++) = (Checksum & 0x00ff);
    *(Point++) = (Checksum >> 8) & 0x00ff;
    // 设定发送DMA发送长度
    *sendLen = totalNumber;
    return DEF_TRUE;
}

/******************************** 主动上传数据 *************************/

/// @brief 心跳包组织函数 0x10
/// @param  none
/// @return 0失败  1成功
uint8_t NetWork_HeartReport(uint16_t syncID){
    uint8_t  os_err;
    uint8_t  Status = DEF_FALSE;
    uint8_t  *Point, *headPoint;
    uint8_t  extendData[DataFrameLength_Extend] = {0};
    uint16_t curZone = 0;
    uint32_t curTimeStamp = 0;
    uint32_t *pLen = NULL;
    
    // 获取信号量
    OSSemPend(App_Sem_NETWORKTX, 0, &os_err);
    // 判断是否可以发送数据
    pLen = WIFI_GetSendLen();
    if ((*pLen) != 0)
        goto NetWork_ExceptionExit;
    // 获取发送缓冲
    Point = (uint8_t *)WIFI_GetSendBuff();
    headPoint = Point;
    // 心跳包内容组织
    Point += DataFrameOrd_Content;
    curTimeStamp = share_RealTimeData_st.CurrentDateTime;
    curZone = share_RealTimeData_st.TimeArea;
    curTimeStamp = NetWork_ConvertTimeFromZone(curTimeStamp, curZone);
    // 本机时区
    memcpy(Point, &curZone, sizeof(curZone));
    Point += 2;
    // 本机时间
    memcpy(Point, &curTimeStamp, sizeof(curTimeStamp));
    Point += 4;
    // 调用数据组织函数进行数据发送
    NetWork_DataFeedback(headPoint, 6, extendData, NetWork_CMD_HeartBeat, syncID, pLen);
    Status = DEF_TRUE;
NetWork_ExceptionExit:
    //释放信号量
    if (OSSemPost(App_Sem_NETWORKTX) != OS_ERR_NONE)
        SYS_DebugERROR;
    return (Status);
}

/// @brief 测试数据主动上报 0x15
/// @param testData_st 测试数据结构体指针
/// @return 0失败  1成功
uint8_t NetWork_TestDataReport(NetWorkTestData_ST * testData_st){
    uint8_t  os_err;
    uint8_t  Status = DEF_FALSE;
    uint8_t  *Point, *headPoint;
    uint8_t  extendData[DataFrameLength_Extend] = {0};
    uint16_t totalNum = 0;
    uint16_t curZone = share_RealTimeData_st.TimeArea;
    uint32_t curTimeStamp = testData_st->finishTimeStamp;
    uint32_t *pLen = NULL;

    // 获取信号量
    OSSemPend(App_Sem_NETWORKTX, 0, &os_err);
    // 判断是否可以发送数据
    pLen = WIFI_GetSendLen();
    if ((*pLen) != 0)
        goto NetWork_ExceptionExit;
    // 获取发送缓冲
    Point = (uint8_t *)WIFI_GetSendBuff();
    headPoint = Point;
    Point += DataFrameOrd_Content;
    // 扩展字段内容组织
    extendData[0] =  testData_st->testType;
    extendData[1] =  testData_st->dataType;
    extendData[2] =  testData_st->packIndex >> 8;
    extendData[3] =  testData_st->packIndex;
    extendData[4] =  testData_st->packNum >> 8;
    extendData[5] =  testData_st->packNum;
    // 测试数据内容组织
    /* 当前时区 */
    memcpy(Point, (char *)&curZone, sizeof(curZone));
    Point += sizeof(curZone);
    totalNum += sizeof(curZone);
    /* 当前时间 */
    memcpy(Point, (char *)&curTimeStamp, sizeof(curTimeStamp));
    Point += sizeof(curTimeStamp);
    totalNum += sizeof(curTimeStamp);
    /* 产品型号 */
    memcpy(Point, (char *)&share_TempConfig_st.procedurePara_st.Product_Model, sizeof(share_TempConfig_st.procedurePara_st.Product_Model));
    Point += sizeof(share_TempConfig_st.procedurePara_st.Product_Model);
    totalNum += sizeof(share_TempConfig_st.procedurePara_st.Product_Model);
    /* 产品编号 */
    memcpy(Point, (char *)&share_TempConfig_st.procedurePara_st.Product_number, sizeof(share_TempConfig_st.procedurePara_st.Product_number));
    Point += sizeof(share_TempConfig_st.procedurePara_st.Product_number);
    totalNum += sizeof(share_TempConfig_st.procedurePara_st.Product_number);
    /* 数据内容 */
    memcpy(Point, testData_st->dataPoint, testData_st->dataLen);
    totalNum += testData_st->dataLen;
    // 调用数据组织函数进行数据发送
    NetWork_DataFeedback(headPoint, totalNum, extendData, NetWork_CMD_TestDataReport, testData_st->syncID,pLen);
    Status = DEF_TRUE;
NetWork_ExceptionExit:
    //释放信号量
    if (OSSemPost(App_Sem_NETWORKTX) != OS_ERR_NONE)
        SYS_DebugERROR;
    return (Status);
}

/******************************** 接收到的响应数据 *************************/

/// @brief 解析心跳包响应  0x10
/// @param sourData 需要解析的数据
static void NetWork_HeartBeatParse(uint8_t *sourData){
    uint16_t localZone = 0, networkZone = 0;
    uint32_t localTime = 0, networkTime = 0;
    uint16_t dataLen = 0;

    dataLen = ((sourData[DataFrameOrd_TotalLength] << 8) | sourData[DataFrameOrd_TotalLength + 1]) - DataFrameLength_Min;
    if (dataLen != 6)
        return;
    // 获取本地时间
    localTime = share_RealTimeData_st.CurrentDateTime;
    localZone = share_RealTimeData_st.TimeArea;
    // 获取网络时间
    networkZone = *(uint16_t *)&sourData[DataFrameOrd_Content];
    networkTime = *(uint32_t *)&sourData[DataFrameOrd_Content + 2];
    if (abs(networkTime - localTime) > 10 || localZone != networkZone){   // 比较网络时间和时区是否和控制器的本地时间或时区相同，如果不同则更新本地时间和时区
        share_RealTimeData_st.CurrentDateTime = networkTime;
        share_RealTimeData_st.TimeArea = networkZone;
        // 更新当前RTC时间
        rtc_TimeAdjust(networkTime);
    }
}

/// @brief 测试数据通知解析 0x15
/// @param sourData 数据源
/// @param syncID 同步ID
/// @return 0失败  1成功
uint8_t NetWork_TestDataInfoParse(uint8_t * sourData, uint16_t syncID){
    uint16_t recvSyncID = 0;

    // 匹配同步ID
    recvSyncID = (sourData[DataFrameOrd_SyncID] << 8) | sourData[DataFrameOrd_SyncID + 1];
    if(recvSyncID != syncID){
        testDataRecvResult = Net_ServerResponse_NG;
        return DEF_FALSE;
    }
    // 判断服务器结果
    if(sourData[DataFrameOrd_Content] == 0){
        testDataRecvResult = Net_ServerResponse_NG;
        return DEF_FALSE;
    }
    testDataRecvResult = Net_ServerResponse_OK;
    return DEF_TRUE;
}

/******************************** 被动上传数据 *************************/

/// @brief 实时数据组织函数 0x11
/// @param  syncID 同步ID
/// @return 0失败  1成功
uint8_t Network_RealTimeData(uint16_t syncID){
    uint8_t  os_err;
    uint8_t  Status = DEF_FALSE;
    uint8_t  *Point, *headPoint;
    uint8_t  extendData[DataFrameLength_Extend] = {0};
    uint16_t dataLen = 0;
    uint32_t *pLen = NULL;

    // 获取信号量
    OSSemPend(App_Sem_NETWORKTX, 0, &os_err);
    // 判断是否可以发送数据
    pLen = WIFI_GetSendLen();
    if ((*pLen) != 0)
        goto NetWork_ExceptionExit;
    // 获取发送缓冲
    Point = (uint8_t *)WIFI_GetSendBuff();
    headPoint = Point;
    Point += DataFrameOrd_Content;
    // 实时数据内容组织
    memcpy(Point, realTimeEnableTable, sizeof(realTimeEnableTable));
    Point += sizeof(realTimeEnableTable);
    dataLen += sizeof(realTimeEnableTable);
    memcpy(Point, &share_RealTimeData_st, sizeof(share_RealTimeData_st));
    dataLen += sizeof(share_RealTimeData_st);
    // 调用数据组织函数进行数据发送
    NetWork_DataFeedback(headPoint, dataLen, extendData, NetWork_CMD_RealTimeData, syncID, pLen);
    Status = DEF_TRUE;
NetWork_ExceptionExit:
    // 释放信号量
    if (OSSemPost(App_Sem_NETWORKTX) != OS_ERR_NONE)
        SYS_DebugERROR;
    return (Status);
}

/// @brief 配置参数查询函数 0x12
/// @param  sourData 数据源
/// @return 0失败  1成功
uint8_t Network_QueryParameterData(uint8_t * sourData)
{
    uint8_t  os_err;
    uint8_t  Status = DEF_FALSE;
    uint8_t  *Point, *headPoint;
    uint8_t  extendData[DataFrameLength_Extend] = {0};
    uint16_t sourDataLen = 0, destDatLen = 0;
    uint16_t syncID = 0;
    uint32_t *pLen = NULL;

    // 获取信号量
    OSSemPend(App_Sem_NETWORKTX, 0, &os_err);
    // 判断是否可以发送数据
    pLen = WIFI_GetSendLen();
    if ((*pLen) != 0)
        goto NetWork_ExceptionExit;
    // 获取发送缓冲
    Point = (uint8_t *)WIFI_GetSendBuff();
    headPoint = Point;
    Point += DataFrameOrd_Content;
    // 指定数据内容组织
    sourDataLen = ((sourData[DataFrameOrd_TotalLength] << 8) | sourData[DataFrameOrd_TotalLength + 1]) - DataFrameLength_Min;
    Status = DataBase_ProtocolContentRead(&sourData[DataFrameOrd_Content], sourDataLen, Point, &destDatLen);
    // 扩展字段配置
    extendData[0] = Status;
    // 获取同步ID
    syncID = (sourData[DataFrameOrd_SyncID] << 8) | sourData[DataFrameOrd_SyncID + 1];
    // 调用数据组织函数进行数据发送
    NetWork_DataFeedback(headPoint, destDatLen, extendData, NetWork_CMD_QueryParameter, syncID, pLen);
NetWork_ExceptionExit:
    // 释放信号量
    if (OSSemPost(App_Sem_NETWORKTX) != OS_ERR_NONE)
        SYS_DebugERROR;
    return (Status);
}

/// @brief 参数配置设定函数 0x13
/// @param  sourData 数据源
/// @return 0失败  1成功
uint8_t Network_SetParameterData(uint8_t * sourData){
    uint8_t  os_err;
    uint8_t  Status = DEF_FALSE;
    uint8_t  *Point, *headPoint;
    uint8_t  extendData[DataFrameLength_Extend] = {0};
    uint16_t sourDataLen = 0;
    uint16_t syncID = 0;
    uint32_t *pLen = NULL;

    // 获取信号量
    OSSemPend(App_Sem_NETWORKTX, 0, &os_err);
    // 判断是否可以发送数据
    pLen = WIFI_GetSendLen();
    if ((*pLen) != 0)
        goto NetWork_ExceptionExit;
    // 获取发送缓冲
    Point = (uint8_t *)WIFI_GetSendBuff();
    headPoint = Point;
    Point += DataFrameOrd_Content;
    // 参数配置内容组织
    sourDataLen = ((sourData[DataFrameOrd_TotalLength] << 8) | sourData[DataFrameOrd_TotalLength + 1]) - DataFrameLength_Min;
    Status = DataBase_ProtocolContentWrite(&sourData[DataFrameOrd_Content], sourDataLen);
    Point[0] = Status;  // 参数设置结果
    // 获取同步ID
    syncID = (sourData[DataFrameOrd_SyncID] << 8) | sourData[DataFrameOrd_SyncID + 1];
    // 调用数据组织函数进行数据发送
    NetWork_DataFeedback(headPoint, 1, extendData, NetWork_CMD_SetParameter, syncID, pLen);
    Status = DEF_TRUE;
NetWork_ExceptionExit:
    //释放信号量
    if (OSSemPost(App_Sem_NETWORKTX) != OS_ERR_NONE)
        SYS_DebugERROR;
    return (Status);
}

/******************************** 测试数据主动上传处理 *************************/

/// @brief 测试基础数据配置
/// @param testType 测试类型
/// @return 0失败  1成功
uint8_t NetWork_TestBaseDataConfig(uint8_t testType){

    switch (testType)
    {
    case WorkflowMode_BuildUpVoltage: // 建压测试基础数据
        netWorkTestData_st.dataAddr  = Addr_EstaMagn_EstablishMagnetic_MinVolt;
        netWorkTestData_st.dataLen   = 16;
        break;
    case WorkflowMode_ExtExcitation: // 极限励磁测试基础数据
        netWorkTestData_st.dataAddr  = Addr_CeilingExci_MaxVoltVolat_U;
        netWorkTestData_st.dataLen   = 60;
        break;
    case WorkflowMode_Volatility: // 波动率测试基础数据
        netWorkTestData_st.dataAddr  = Addr_Volatility_MaxVoltVolat_U;
        netWorkTestData_st.dataLen   = 100;
        break;
    case WorkflowMode_LowFreProte: // 低频保护测试基础数据
        netWorkTestData_st.dataAddr  = Addr_UnderFreq_SteadyVoltage_U;
        netWorkTestData_st.dataLen   = 40;
        break;
    case WorkflowMode_Tuning0APF:   // 整定测试基础数据
    case WorkflowMode_Tuning08PF:
    case WorkflowMode_Tuning06A04PF: 
        netWorkTestData_st.dataAddr  = Addr_Upload_GenActiPower_U;
        netWorkTestData_st.dataLen   = 184;
        break;
    case WorkflowMode_StartStop: // 启停测试基础数据
        netWorkTestData_st.dataAddr  = Addr_StartStop_MaxExciGenVolt_start;
        netWorkTestData_st.dataLen   = 48;
        break;
    case WorkflowMode_LoadUnLoad: // 突卸测试基础数据
        netWorkTestData_st.dataAddr  = Addr_SuddenUnload_PhaseVoltAver_U;
        netWorkTestData_st.dataLen   = 96;
        break;
    default:
        break;
    }
    // 公共配置
    netWorkTestData_st.testType  = testType;
    netWorkTestData_st.dataType  = 1;
    netWorkTestData_st.packIndex = 1;
    netWorkTestData_st.packNum   = 1;
    netWorkTestData_st.dataPoint = network_TmepDataBuff;
    netWorkTestData_st.syncID    = NetWork_UpdateWifiSyncID();
    netWorkTestData_st.finishTimeStamp = share_RealTimeData_st.CurrentDateTime;
    // 从数据库中读取内容
    if(DataBase_ReadDataContent(netWorkTestData_st.dataAddr, (uint16_t *)netWorkTestData_st.dataPoint, netWorkTestData_st.dataLen / 2) == DEF_FALSE)
        return DEF_FALSE;
    return DEF_TRUE;
}

/// @brief 测试曲线数据配置
/// @param testType 测试类型
/// @return 0失败  1成功
uint8_t NetWork_TestCurveDataConfig(uint8_t testType){
    uint16_t buffsize = TEMPBUFF_DATA_SIZE;

    switch (testType)
    {
    case WorkflowMode_BuildUpVoltage: // 建压测试曲线数据
        netWorkTestData_st.dataAddr        = Addr_EstaMagn_VoltDataNumber;
        netWorkTestData_st.curveAddr       = Addr_EstaMagn_GenVoltDataCurve;
        netWorkTestData_st.curveDataLen    = share_EstaMagnData_st.baseData_st.VoltDataNumber * SRAM_EstaMagn_CurvePointSize;
        netWorkTestData_st.curveAddrOffset = (SRAM_EstaMagn_CurvePointSize * SRAM_EstaMagn_CurvePointMaxNum) / 2;
        netWorkTestData_st.totalPackLen    = netWorkTestData_st.curveDataLen * SRAM_EstaMagn_CurveTypeNum;
        break;
    case WorkflowMode_ExtExcitation: // 极限励磁测试曲线数据
        netWorkTestData_st.dataAddr        = Addr_CeilingExci_VoltDataNumber;
        netWorkTestData_st.curveAddr       = Addr_CeilingExci_GenVoltDataCurve;
        netWorkTestData_st.curveDataLen    = share_CeilingExciData_st.baseData_st.VoltDataNumber * SRAM_CeilingExci_CurvePointSize;
        netWorkTestData_st.curveAddrOffset = (SRAM_CeilingExci_CurvePointSize * SRAM_CeilingExci_CurvePointMaxNum) / 2;
        netWorkTestData_st.totalPackLen    = netWorkTestData_st.curveDataLen * SRAM_CeilingExci_CurveTypeNum;
        break;
    case WorkflowMode_Volatility: // 波动率测试曲线数据
        netWorkTestData_st.dataAddr        = Addr_Volatility_VoltDataNumber;
        netWorkTestData_st.curveAddr       = Addr_Volatility_VoltDataCurve_U;
        netWorkTestData_st.curveDataLen    = share_VolatilityData_st.baseData_st.VoltDataNumber * SRAM_Volatility_CurvePointSize;
        netWorkTestData_st.curveAddrOffset = (SRAM_Volatility_CurvePointSize * SRAM_Volatility_CurvePointMaxNum) / 2;
        netWorkTestData_st.totalPackLen    = netWorkTestData_st.curveDataLen * SRAM_Volatility_CurveTypeNum;
        break;
    case WorkflowMode_LowFreProte: // 低频保护测试曲线数据
        netWorkTestData_st.dataAddr        = Addr_UnderFreq_VoltDataNumber;
        netWorkTestData_st.curveAddr       = Addr_UnderFreq_GenVoltDataCurve;
        netWorkTestData_st.curveDataLen    = share_UnderFreqData_st.baseData_st.VoltDataNumber * SRAM_UnderFreq_CurvePointSize;
        netWorkTestData_st.curveAddrOffset = (SRAM_UnderFreq_CurvePointSize * SRAM_UnderFreq_CurvePointMaxNum) / 2;
        netWorkTestData_st.totalPackLen    = netWorkTestData_st.curveDataLen * SRAM_UnderFreq_CurveTypeNum;
        break;
    case WorkflowMode_Tuning0APF:   // 整定测试曲线数据
    case WorkflowMode_Tuning08PF:
    case WorkflowMode_Tuning06A04PF:
        netWorkTestData_st.dataAddr        = Addr_Upload_VoltDataNumber;
        netWorkTestData_st.curveAddr       = Addr_Upload_VoltDataCurve_U;
        netWorkTestData_st.curveDataLen    = share_UploadData_st.baseData_st.VoltDataNumber * SRAM_Upload_CurvePointSize;
        netWorkTestData_st.curveAddrOffset = (SRAM_Upload_CurvePointSize * SRAM_Upload_CurvePointMaxNum) / 2;
        netWorkTestData_st.totalPackLen    = netWorkTestData_st.curveDataLen * SRAM_Upload_CurveTypeNum;
        break;
    case WorkflowMode_StartStop: // 启停测试曲线数据
        netWorkTestData_st.dataAddr        = Addr_StartStop_VoltDataNumber;
        netWorkTestData_st.curveAddr       = Addr_StartStop_GenVoltCurve;
        netWorkTestData_st.curveDataLen    = share_StartStopData_st.baseData_st.VoltDataNumber * SRAM_StartStop_CurvePointSize;
        netWorkTestData_st.curveAddrOffset = (SRAM_StartStop_CurvePointSize * SRAM_StartStop_CurvePointMaxNum) / 2;
        netWorkTestData_st.totalPackLen    = netWorkTestData_st.curveDataLen * SRAM_StartStop_CurveTypeNum;
        break;
    case WorkflowMode_LoadUnLoad: // 突卸测试曲线数据
        netWorkTestData_st.dataAddr        = Addr_SuddenUnload_VoltDataNumber;
        netWorkTestData_st.curveAddr       = Addr_SuddenUnload_VoltDataCurve_U;
        netWorkTestData_st.curveDataLen    = share_SuddenUnloadData_st.baseData_st.VoltDataNumber * SRAM_SuddenUnload_CurvePointSize;
        netWorkTestData_st.curveAddrOffset = (SRAM_SuddenUnload_CurvePointSize * SRAM_SuddenUnload_CurvePointMaxNum) / 2;
        netWorkTestData_st.totalPackLen    = netWorkTestData_st.curveDataLen * SRAM_SuddenUnload_CurveTypeNum;
    default:
        break;
    }
    // 公共配置
    netWorkTestData_st.testType       = testType;
    netWorkTestData_st.dataType       = 2;
    netWorkTestData_st.packIndex      = 1;
    netWorkTestData_st.packNum        = (((netWorkTestData_st.totalPackLen + 4) % buffsize) == 0) ? ((netWorkTestData_st.totalPackLen + 4) / buffsize) : ((netWorkTestData_st.totalPackLen + 4) / buffsize + 1);
    netWorkTestData_st.dataPoint      = network_TmepDataBuff;
    netWorkTestData_st.remainPackLen  = netWorkTestData_st.totalPackLen;
    // 如果曲线数据为0则不发送曲线数据
    if(netWorkTestData_st.curveDataLen == 0)
        return DEF_FALSE;
    return DEF_TRUE;
}

/// @brief 测试曲线数据发送
/// @param  none
/// @return 0失败  1成功
uint8_t NetWork_TestCurveDataSend(void){
    uint8_t * dataPoint = netWorkTestData_st.dataPoint;
    uint16_t curCurveRemainLen = 0; // 当前曲线剩余长度
    uint16_t curRemainSendLen = 0;  // 剩余发送长度
    uint16_t readLen = 0;           // 读取长度
    uint32_t readAddr = 0;          // 读取地址
    uint32_t startPosition = 0;     // 开始位置

    // 本次需要发送的长度
    if(netWorkTestData_st.remainPackLen >= TEMPBUFF_DATA_SIZE)
        netWorkTestData_st.dataLen = TEMPBUFF_DATA_SIZE;
    else if(netWorkTestData_st.remainPackLen < TEMPBUFF_DATA_SIZE && netWorkTestData_st.packNum == 1)
        netWorkTestData_st.dataLen = netWorkTestData_st.remainPackLen + 4;
    else
        netWorkTestData_st.dataLen = netWorkTestData_st.remainPackLen;
    // 第一个数据包需要包含曲线点数和采样点数
    if(netWorkTestData_st.packIndex == 1){
        if(DataBase_ReadDataContent(netWorkTestData_st.dataAddr, (uint16_t *)dataPoint, 2) == DEF_FALSE)
            return DEF_FALSE;
        dataPoint += 4;
        curRemainSendLen = (netWorkTestData_st.dataLen - 4) / 2;
    }
    else{
        curRemainSendLen = netWorkTestData_st.dataLen / 2;
    }
    // 曲线数据开始位置
    startPosition = netWorkTestData_st.totalPackLen - netWorkTestData_st.remainPackLen;
    // 获取需要发送的数据
    while(curRemainSendLen){
        readAddr = netWorkTestData_st.curveAddr + ((startPosition / netWorkTestData_st.curveDataLen) * netWorkTestData_st.curveAddrOffset) + (startPosition % netWorkTestData_st.curveDataLen) / 2;
        curCurveRemainLen = (netWorkTestData_st.curveDataLen - startPosition % netWorkTestData_st.curveDataLen) / 2;
        if(curCurveRemainLen >= curRemainSendLen)
            readLen = curRemainSendLen;
        else
            readLen = curCurveRemainLen;
        // 读取数据
        if(DataBase_ReadDataContent(readAddr, (uint16_t *)dataPoint, readLen) == DEF_FAIL)
            return DEF_FALSE;
        // 数据偏移
        dataPoint += readLen * 2;
        startPosition += readLen * 2;
        curRemainSendLen -= readLen;
    }
    // 往服务器发送数据
    if(NetWork_TestDataReport(&netWorkTestData_st) == DEF_FALSE)
        return DEF_FALSE;
    return DEF_TRUE;
}

/// @brief 主动上报数据处理函数
/// @param tick 时间片
void NetWork_TestDataUploadHandle(uint8_t tick){
    static uint8_t workProcType = 0;
    static uint16_t OverTime = 0, OverTimer = 0;

    // 判断WIFI状态是否正常
    if(WIFI_GetStatus() < sWIFI_AT_CheckSend || already_send_transient != 0)
        return;
    // 判断是否有完成的数据需要上传
    if(networkTestProc_st.finishFlag == 1){
        OverTime = 60;
        workProcess  = 1;
        curveDataSending = 1;
        workProcType = networkTestProc_st.workProcType;
        NetWork_ClrTestFisishFlag();
    }
    // 数据延迟发送3秒
    if(workProcess == 1 && OverTime != 0){
        OverTime --;
        return;
    }
    // 判断是否启动数据发送
    if(curveDataSending == DEF_FALSE){
        return;
    }
    // 工作流程
    switch (workProcess){
    case UpProc_CfgBasedat: // 配置基础数据
        NetWork_TestBaseDataConfig(workProcType);
        workProcess = UpProc_SendBaseData;
        break;
    case UpProc_SendBaseData: // 发送基础数据
        OverTime = 0;
        testDataRecvResult = Net_ServerResponse_None;
        if(NetWork_TestDataReport(&netWorkTestData_st) == DEF_TRUE)
            workProcess = UpProc_WaitAck1;
        break;
    case UpProc_WaitAck1: // 等待服务器响应
        if(testDataRecvResult == Net_ServerResponse_NG){
            OverTimer++;
            workProcess = UpProc_SendBaseData;
        }
        else if(testDataRecvResult == Net_ServerResponse_OK)
            workProcess = UpProc_CfgCurveData;
        OverTime += 1;
        // 超时没有收到服务器响应，重新发送数据
        if(OverTime > 40){
            workProcess = UpProc_SendBaseData;
            OverTimer += 1;
        }
        // 重新发送数据5次没有响应或NG响应则取消发送
        if(OverTimer >= 5){
            workProcess = UpProc_Error;
        }
        break;
    case UpProc_CfgCurveData: // 配置曲线数据
        if(NetWork_TestCurveDataConfig(workProcType) == DEF_TRUE)
            workProcess = UpProc_SendCurveData;
        else
            workProcess = UpProc_Error;
        OverTimer = 0;
        break;
    case UpProc_SendCurveData: // 发送曲线数据
        OverTime = 0;
        testDataRecvResult = Net_ServerResponse_None;
        if(NetWork_TestCurveDataSend() == DEF_TRUE)
            workProcess = UpProc_WaitAck2;
        break;
    case UpProc_WaitAck2: // 等待服务器响应
        if(testDataRecvResult == Net_ServerResponse_NG){
            OverTimer++;
            workProcess = UpProc_SendCurveData;
        }
        else if(testDataRecvResult == Net_ServerResponse_OK){
            // 剩余包大小自减
            if(netWorkTestData_st.packIndex == 1)
                netWorkTestData_st.remainPackLen -= (netWorkTestData_st.dataLen - 4);
            else
                netWorkTestData_st.remainPackLen -= netWorkTestData_st.dataLen;
            // 分包索引自增
            netWorkTestData_st.packIndex += 1;
            // 跳转到下一个流程
            workProcess = UpProc_SendOKJudge;
        }
        OverTime += 1;
        // 超时没有收到服务器响应，重新发送数据
        if(OverTime > 40){
            workProcess = UpProc_SendCurveData;
            OverTimer += 1;
        }
        // 重新发送数据5次没有响应或NG响应则取消发送
        if(OverTimer >= 5){
            workProcess = UpProc_Error;
        }
        break;
    case UpProc_SendOKJudge: // 判断发送完成
        if(netWorkTestData_st.packIndex <= netWorkTestData_st.packNum)
            workProcess = UpProc_SendCurveData;
        else
            workProcess = UpProc_ClearFlag;
        break;
    case UpProc_ClearFlag: // 清除标志
        workProcess  = 0;
        curveDataSending  = 0;
        workProcType = 0;
        OverTimer = 0;
        OverTime = 0;
        break;
    case UpProc_Error: // 异常处理
        workProcess  = 0;
        curveDataSending  = 0;
        workProcType = 0;
        OverTimer = 0;
        OverTime = 0;
        break;
    default:
        workProcess = 0;
        break;
    }
}

/******************************** 其他一些杂项函数 *************************/

/// @brief 设定测试完成标志
/// @param testType 测试类型
void NetWork_SetTestFisishFlag(uint8_t testType){
    uint8_t os_err = 0;
    // 由于干扰影响先复位WIFi模块再发曲线数据
    // WIFI_Init();
    // 获取信号量
    OSSemPend((OS_EVENT *)App_Sem_NETWORKTEST,0,&os_err);
    networkTestProc_st.finishFlag = 1;
    networkTestProc_st.workProcType = testType;
    // 释放信号量
    OSSemPost((OS_EVENT *)App_Sem_NETWORKTEST);
    OSTimeDlyHMSM(0,0,10,0);
}

/// @brief 清除测试完成标志
/// @param  none
void NetWork_ClrTestFisishFlag(void){
    uint8_t os_err = 0;

    // 获取信号量
    OSSemPend((OS_EVENT *)App_Sem_NETWORKTEST,0,&os_err);
    networkTestProc_st.finishFlag = 0;
    // 释放信号量
    OSSemPost((OS_EVENT *)App_Sem_NETWORKTEST);
}

/******************************** 数据中转及处理函数 *************************/

/// @brief 平台下发数据处理函数
/// @param sourData 数据源
/// @param cmd 命令码
static void NetWork_DataHandle(uint8_t *sourData, uint8_t cmd){
    uint16_t syncID = 0;

    // 收到平台数据清除心跳包计时
    heartBeatReport_st.totalTimer = 0;
    heartBeatReport_st.sendTimer = 0;
    // 获取同步ID
    syncID = (sourData[DataFrameOrd_SyncID] << 8) | sourData[DataFrameOrd_SyncID + 1];
    // 根据命令号选择不同的函数去处理数据
	if (cmd == NetWork_CMD_HeartBeat)
		NetWork_HeartBeatParse(sourData);                                  // 处理接收到的心跳包
	else if (cmd == NetWork_CMD_RealTimeData && curveDataSending == 0)
		Network_RealTimeData(syncID);                                      // 处理实时数据
	else if (cmd == NetWork_CMD_QueryParameter && curveDataSending == 0)
		Network_QueryParameterData(sourData);                              // 处理参数查询
    else if (cmd == NetWork_CMD_SetParameter && curveDataSending == 0)
        Network_SetParameterData(sourData);                                // 处理参数设置
    else if (cmd == NetWork_CMD_TestDataReport)
        NetWork_TestDataInfoParse(sourData, netWorkTestData_st.syncID);    // 处理测试数据包响应
}

/// @brief TCP数据处理(黏包/拆包)
/// @param recv_buffer 接收到的数据
/// @param recv_length 接收到的长度
static void NetWork_TCP_DataProcess(uint8_t *recv_buffer, uint16_t recv_length){
    static u16 buffer_length = 0;       // 第一次
    uint8_t *SerDataBuffer;
    RET_FINDSUB ret_findSub;
    uint16_t length, calChecksum, BufCheckSum;

    HandleFlag = 1;

    // 检查接收数据的有效性
    if (recv_buffer == NULL || recv_length == 0){
        HandleFlag = 0;
        return;
    }
    // 当缓冲区数据溢出时，重置缓冲区
    if (buffer_length + recv_length > DMARxBuffer){
        buffer_length = 0;
    }
    // 将新接收到的数据复制到缓冲区中
    memcpy(network_ParseBuffer + buffer_length, recv_buffer, recv_length);
    buffer_length += recv_length;

    while (buffer_length >= DataFrameLength_TUANCHENG + DataFrameLength_TotalLength){
        /* 查找标志 */
        ret_findSub = Comm_StrStr((char *)network_ParseBuffer, (char *)NetworkString_TUANCHENG, buffer_length);
        if (ret_findSub.adr == NULL){
            buffer_length = 0;
            break;
        }
        else if (ret_findSub.index != 0){
            memmove(network_ParseBuffer, ret_findSub.adr, buffer_length - ret_findSub.index);
            buffer_length -= ret_findSub.index;
        }
        // 数据包长度
        length = (network_ParseBuffer[DataFrameOrd_TotalLength] << 8) | network_ParseBuffer[DataFrameOrd_TotalLength + 1];
        // 数据不够
        if (buffer_length < length){
            break;
        }
        // 校验和验证
        calChecksum = Comm_CalCheckSum(network_ParseBuffer, length - 2);
        BufCheckSum = (network_ParseBuffer[length - 1] << 8) | network_ParseBuffer[length - 2];
        if (calChecksum != BufCheckSum){
            // 移除header
            memmove(network_ParseBuffer, network_ParseBuffer + DataFrameLength_TUANCHENG, buffer_length - DataFrameLength_TUANCHENG);
            buffer_length -= DataFrameLength_TUANCHENG;
            continue;
        }
        SerDataBuffer = (u8 *)malloc(length);
        if (SerDataBuffer == NULL){
            buffer_length = 0;
            break;
        }

        memcpy(SerDataBuffer, network_ParseBuffer, length);
        if (OSQPostOpt(App_Q_NETHANDLE, SerDataBuffer, OS_POST_OPT_NONE) != OS_ERR_NONE){
            // 消息满了，不再处理
            buffer_length = 0;
            free(SerDataBuffer);
            break;
        }

        // 从缓冲区中移除已处理的数据
        memmove(network_ParseBuffer, network_ParseBuffer + length, buffer_length - length);
        buffer_length -= length;
    }
    HandleFlag = 0;
}

/******************************** 网络流程任务函数 *************************/

/// @brief 网络流程任务
/// @param p_arg 参数
void App_Task_NetWork_Flow(void *p_arg){
    uint8_t os_err;
    OS_FLAGS os_value;
    (void)p_arg;

    /* Wait for Start action finish */
//    OSSemPend(App_Sem_STARTSYNC, 0, &os_err);

    WIFI_Init();

    while (DEF_TRUE){
        /*  Wait for State Update output Flags  */
        os_value = OSFlagPend(App_Flags_NETWORK,
                              OSNETWORKFlags_ALL,
                              OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
                              0,
                              &os_err);
        if (os_err != OS_ERR_NONE)
            SYS_DebugERROR;
        // 50ms定时事件
        if (os_value & OSNETWORKFlags_Scand) {
            WIFI_ProcessHandle(50); // 定时扫描状态机，执行状态机中的AT指令进行数据的发送和接收。参数50间隔50ms扫描一次
            NetWork_TestDataUploadHandle(50); // 定时扫描是否有需要主动上报的数据
        }
        // 100ms定时事件
        if (os_value & OSNETWORKFlags_Timing){
            WIFI_HeartReportHandle(); // 定时检查socket连接状态，以及心跳包维护
        }
    }
}

/// @brief 数据解析任务
/// @param p_arg 参数
void App_Task_NetWork_Parse(void *p_arg)
{
    OS_FLAGS os_value;
    uint8_t os_err, curIndex;
    uint8_t * dataPoint = NULL;
    uint8_t tempBuf[5] = {0};
    char *pRecvCmd, *pBuff1;
    uint32_t ret, len;
    (void)p_arg;

    /* Wait for Start action finish */
//    OSSemPend(App_Sem_STARTSYNC, 0, &os_err);

    while (DEF_TRUE){
        /*  Wait for State Update output Flags  */
        os_value = OSFlagPend(App_Flags_NETPARSE,
                              OSNETWORKHandleCacheFlags_ALL,
                              OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
                              0,
                              &os_err);
        if (os_err != OS_ERR_NONE){
            SYS_DebugERROR;
        }

        // 处理缓存接收字符
        if (os_value & DEF_BIT_00)
            curIndex = 0;
        if (os_value & DEF_BIT_01)
            curIndex = 1;
        TemArrRxBuffer[curIndex][sRecv_LEN] = 0x00; // 在接收到的DMA缓冲中字符串末尾加上0x00作为结尾
        // AT指令的响应
        pRecvCmd = strstr((char *)&TemArrRxBuffer[curIndex][0], pGPRS_AT->pATRecv);
        if (pRecvCmd != NULL){
            ret = strlen(pGPRS_AT->pATRecv);                   // 计算待比较的字符串的长度，如果是
            len = sRecv_LEN - ret;                             // 计算减掉待比较的字符串之后的字符串长度
            ret = pGPRS_AT->recvFunction(&pRecvCmd[ret], len); // 以接收到的字符串中参数2位置为首地址，调用接收函数
            if (ret == 1){
                WIFI_SetStatus(pGPRS_AT->ucNextStatus); // 收到EC20的正常返回指令时，跳转到下一个流程
            }
        }
        // 收到平台下发的数据
        dataPoint = &TemArrRxBuffer[curIndex][0];
        while (ucStatus > sWIFI_AT_CloseSocket){
            pBuff1 = strstr((char *)dataPoint, "+IPD");
            if (pBuff1 != NULL){
                pBuff1 = strstr((char *)dataPoint, ",");
                pBuff1 += 1;
                strncpy((char *)tempBuf, pBuff1, 3);
                len = atoi((char *)tempBuf);
                // 如果数据长度为0 ，说明没收到平台的数据
                if (len == 0)
                    goto HANDLEEND; 
                // 检查长度数据是否存在错误
                if (len >= DMARxBuffer)
                    goto HANDLEEND; 
                // 偏移到数据内容处
                pBuff1 = strstr((char *)dataPoint, ":");
                pBuff1 += 1;
                // 检查字符串的后面是否为空
                if (pBuff1 == NULL)
                    goto HANDLEEND; 
                // 等待处理完成
                if (HandleFlag == 0)
                    NetWork_TCP_DataProcess((uint8_t *)pBuff1, len);
                dataPoint += (len + 11);
            }
            // 接收SOCKET被关闭的消息
            else if (strstr((char *)&TemArrRxBuffer[curIndex][0], "CLOSED") != NULL){
                WIFI_SetStatus(sWIFI_AT_CloseSocket);
                break;
            }
            else
                break;
        }

    HANDLEEND:
        //  避免一直在处理数据
        OSTimeDlyHMSM(0, 0, 0, 10);
    }
}

/// @brief 数据处理任务
/// @param p_arg 参数
void App_Task_NetWork_Handle(void *p_arg)
{
    void *os_msg;
    u8 *buffer;
    uint8_t os_err;
    uint8_t cmd = 0;
    u32 *pLen;

    /* Wait for Start action finish */
//    OSSemPend(App_Sem_STARTSYNC, 0, &os_err);

    while (DEF_TRUE){
        os_msg = OSQPend(App_Q_NETHANDLE, 0, &os_err);
        if (os_err != OS_ERR_NONE)
            continue;
        while (1){
            pLen = WIFI_GetSendLen();
            if (*pLen != 0)
                OSTimeDlyHMSM(0, 0, 0, 10);
            else
                break;
        }

        if (os_msg != NULL){
            buffer = (u8 *)os_msg;
            cmd = buffer[DataFrameOrd_Command];
            // 处理数据
            NetWork_DataHandle(buffer, cmd);
            // 释放内存
            free(os_msg);
        }
    }
}

#endif
